﻿namespace GreenIsomer.Web.Controls.JQuery {
	using System;
	using System.Web.UI;
	using System.Web.UI.WebControls;
	using System.Collections.Specialized;
	using System.ComponentModel;
	using System.Diagnostics.CodeAnalysis;

	/// <summary>
	/// Provides a validated client hidden input field enabling the jQuery widgets to write state changes back to the server for post back.
	/// </summary>
	[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "BackField", Justification = "Post-Back Field, not Post Backfield")]
	public class PostBackField : Control, IPostBackDataHandler {


		#region Members

		private string oldValue;
		private string newValue;

		#endregion


		#region Constructors

		/// <summary>
		/// Initializes a new instance of the GreenIsomer.Web.Controls.JQuery.PostbackField class.
		/// </summary>
		public PostBackField() { }

		#endregion


		#region Properties

		/// <summary>
		/// Gets or sets the value to render and post back to the client.
		/// </summary>
		public virtual string Value {
			get { return ViewState["Value"] as string ?? string.Empty; }
			set { ViewState["Value"] = value; }
		}

		#endregion


		#region Events

		/// <summary>
		/// Occurs when the value sent to the client is changed before posting back to the server.
		/// </summary>
		[Category("Action")]
		public event EventHandler<PostBackFieldEventArgs> ValueChanged;

		#endregion


		#region Methods: Event hooks

		/// <summary>
		/// Raises the ValueChanged event.
		/// </summary>
		/// <param name="e">The GreenIsomer.Web.Controls.JQuery.PostbackEventArgs object that contains the event data.</param>
		protected virtual void OnValueChanged(PostBackFieldEventArgs e) {
			if(ValueChanged != null) ValueChanged.Invoke(this, e);
		}

		#endregion


		#region Methods: Rendering hooks

		/// <summary>
		/// Raises the System.Web.UI.Control.PreRender event.
		/// </summary>
		/// <param name="e">The System.EventArgs object that contains the event data.</param>
		protected override void OnPreRender(EventArgs e) {
			base.OnPreRender(e);

			Page.RegisterRequiresPostBack(this);
		}

		/// <summary>
		/// Sends server control content to a provided System.Web.UI.HtmlTextWriter object, which writes the content to be rendered to the client.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="writer">A System.Web.UI.HtmlTextWriter that represents the output stream to render HTML content on the client.</param>
		protected override void Render(HtmlTextWriter writer) {
			base.Render(writer);
			PostBackOptions options = new PostBackOptions(this);
			Page.ClientScript.RegisterForEventValidation(options);
			Page.ClientScript.RegisterHiddenField(ClientID, Value);
		}

		/// <summary>
		/// Processes postback data for an ASP.NET server control.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="postDataKey">The key identifier for the control.</param>
		/// <param name="postCollection">The collection of all incoming name values.</param>
		/// <returns>True if the server control's state changes as a result of the postback; otherwise, false.</returns>
		protected virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection) {

			Page.ClientScript.ValidateEvent(postDataKey);

			oldValue = Value;
			newValue = postCollection[ClientID];

			if(newValue == oldValue) return false;

			Value = newValue;
			return true;
		}

		#endregion


		#region Explicit implementation: IPostBackDataHandler

		bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection) {
			return LoadPostData(postDataKey, postCollection);
		}

		[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "It's called OnValueChanged")]
		void IPostBackDataHandler.RaisePostDataChangedEvent() {
			OnValueChanged(new PostBackFieldEventArgs(oldValue, newValue));
		}

		#endregion


	}

}